#region using
using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Text;
using System.Xml;

using DbmlManager.Lib.Utility;

// using MySql.Data.MySqlClient;
#endregion

namespace DbmlManager.Lib.Database
{
  #region Class Docs
  /// <summary>
  /// Summary description for DbConnectionInfo.
  /// </summary>
  #endregion

	[Serializable]
	public class DbConnectionInfo : ChangeableObjectBase, IDbConnectionInfo
	{
		// Constructors

		#region DbConnectionInfo()
		public DbConnectionInfo()
		{
			_storageType = StorageTypeEnum.SqlServer;
			_serverName = Environment.MachineName;
			_port = "3306";  // MySQL default
			_dbName = String.Empty;
		}
		#endregion

		#region DbConnectionInfo(StorageTypeEnum storageType, string serverName, string dbName)
		public DbConnectionInfo(StorageTypeEnum storageType, string serverName, string dbName)
		{
			_storageType = storageType;
			_serverName = (serverName == null) ? string.Empty : serverName;
			_dbName = (dbName == null) ? string.Empty : dbName;
		}
		#endregion
    
		#region DbConnectionInfo(IDbConnectionInfo dbci)
		public DbConnectionInfo(IDbConnectionInfo dbci)
		{
			Copy(dbci);
		}
		#endregion

		#region DbConnectionInfo(XmlDocument xml, XmlNode parent)
		public DbConnectionInfo(XmlDocument xml, XmlNode parent)
		{
			LoadFromXml(xml, parent);
		}
		#endregion

		// Public Properties

		#region StorageType
		public virtual StorageTypeEnum StorageType
		{
			get
			{
				return _storageType;
			}
			set
			{
				_storageType = value;
			}
		}
		private StorageTypeEnum _storageType = StorageTypeEnum.SqlServer;
		#endregion

		#region ServerName
		public string ServerName
		{
			get
			{
				return _serverName;
			}
			set
			{
				SetStringVal(ref _serverName, value);
			}
		}
		private string _serverName = string.Empty;
		#endregion

		#region Port
		public string Port
		{
			get
			{
				return _port;
			}
			set
			{
				SetStringVal(ref _port, value);
			}
		}
		private string _port = string.Empty;
		#endregion

		#region DbName
		public string DbName
		{
			get
			{
				return _dbName;
			}
			set
			{
				SetStringVal(ref _dbName, value);
			}
		}
		private string _dbName = string.Empty;
		#endregion

		#region UserName
		public string UserName
		{
			get
			{
				return _userName;
			}
			set
			{
				SetStringVal(ref _userName, value);
			}
		}
		private string _userName = string.Empty;
		#endregion

		#region Password
		public string Password
		{
			get
			{
				return _password;
			}
			set
			{
				SetStringVal(ref _password, value);
			}
		}
		private string _password = string.Empty;
		#endregion

		#region HasConnectionSettings
		public bool HasConnectionSettings
		{
			get
			{
				return ServerName != null && ServerName != String.Empty && DbName != null && DbName != String.Empty;
			}
		}
		#endregion

		#region AuthenticationMethod
		public DbAuthenticationMethods AuthenticationMethod
		{
			get
			{
				return _authenticationMethod;
			}
			set
			{
				SetAuthVal(ref _authenticationMethod, value);
			}
		}
		private DbAuthenticationMethods _authenticationMethod = DbAuthenticationMethods.UseIntegratedSecurity;
		#endregion

		#region AppendExtraConnectionString
		public bool AppendExtraConnectionString
		{
			get
			{
				return _appendExtraConnectionString;
			}
			set
			{
				SetBoolVal(ref _appendExtraConnectionString, value);
			}
		}
		private bool _appendExtraConnectionString = false;
		#endregion

		#region ExtraConnectionString
		public string ExtraConnectionString
		{
			get
			{
				return _extraConnectionString;
			}
			set
			{
				SetStringVal(ref _extraConnectionString, value);
			}
		}
		private string _extraConnectionString = string.Empty;
		#endregion

		#region UseCustomConnectionString
		public bool UseCustomConnectionString
		{
			get
			{
				return _useCustomConnectionString;
			}
			set
			{
				SetBoolVal(ref _useCustomConnectionString, value);
			}
		}
		private bool _useCustomConnectionString = false;
		#endregion

		#region CustomConnectionString
		public string CustomConnectionString
		{
			get
			{
				return _customConnectionString;
			}
			set
			{
				SetStringVal(ref _customConnectionString, value);
			}
		}
		private string _customConnectionString = string.Empty;
		#endregion

		#region ConnectionString
		public virtual string ConnectionString
		{
			get
			{
				if (StorageType == StorageTypeEnum.SqlServer)
				{
					if (AuthenticationMethod == DbAuthenticationMethods.UseIntegratedSecurity)
						return String.Format("Data Source={0}; Initial Catalog={1}; Pooling=False; Integrated Security=SSPI;", _serverName, _dbName);
					else
						return String.Format("Data Source={0}; Initial Catalog={1}; Pooling=False; Trusted_Connection=False; User ID={2}; Password={3};", _serverName, _dbName, UserName, Password);
				}
				else if (StorageType == StorageTypeEnum.MySql)
					return String.Format("Server={0};Port={1};Database={2};User ID={3};Password={4};Pooling=False",
						ServerName, Port, DbName, UserName, Password);
				else
					return "";
			}
		}
		#endregion

		#region ParameterMarker
		public char ParameterMarker
		{
			get
			{
				if (_storageType == StorageTypeEnum.MySql)
					return '?';
				else
					return '@';
			}
		}
		#endregion

		// Public Methods

		#region Copy(IDbConnectionInfo dbci)
		public void Copy(IDbConnectionInfo dbci)
		{
			base.Copy(dbci);
			_storageType = dbci.StorageType;
			_serverName = dbci.ServerName;
			_dbName = dbci.DbName;
			_userName = dbci.UserName;
			_password = dbci.Password;
			_port = dbci.Port;
			_authenticationMethod = dbci.AuthenticationMethod;
			_appendExtraConnectionString = dbci.AppendExtraConnectionString;
			_extraConnectionString = dbci.ExtraConnectionString;
			_useCustomConnectionString = dbci.UseCustomConnectionString;
			_customConnectionString = dbci.CustomConnectionString;
		}
		#endregion

		#region DbCreator()
		public IDbCreator DbCreator()
		{
      //if (_storageType == StorageTypeEnum.MySql)
      //  return new MySqlDbCreator(this);
      //else
				return new SqlDbCreator(this);
		}
		#endregion

		#region Connection()
		public IDbConnection Connection()
		{
      //if (_storageType == StorageTypeEnum.MySql)
      //  return new MySqlConnection(ConnectionString);
      //else
				return new SqlConnection(ConnectionString);
		}
		#endregion

		// IXmlSupport Implementation

		#region InjectXml(XmlDocument xml, XmlNode parent)
		public void InjectXml(XmlDocument xml, XmlNode parent)
		{
			XmlElement dbci = xml.CreateElement("DbConnectionInfo");

      //string hashKey = EncryptUtil.GenerateRandomKey();
      //string fullPassword = hashKey + CPUId + MACAddr;
			XmlUtil.AddXmlElement(xml, dbci, "StorageType", DbmlManager.Lib.Database.StorageType.ToString(StorageType));
			XmlUtil.AddXmlElement(xml, dbci, "ServerName", ServerName);
			XmlUtil.AddXmlElement(xml, dbci, "Port", Port);
			XmlUtil.AddXmlElement(xml, dbci, "DbName", DbName);
      //XmlUtil.AddXmlElement(xml, dbci, "UserName", EncryptUtil.EncryptString(UserName, fullPassword));
      //XmlUtil.AddXmlElement(xml, dbci, "Password", EncryptUtil.EncryptString(Password, fullPassword));
			XmlUtil.AddXmlElement(xml, dbci, "Encrypted", "1");
      //XmlUtil.AddXmlElement(xml, dbci, "Hash", hashKey);
			XmlUtil.AddXmlElement(xml, dbci, "AuthenticationMethod", ((int) AuthenticationMethod).ToString());
			XmlUtil.AddXmlElement(xml, dbci, "AppendExtraConnectionString", AppendExtraConnectionString ? "1" : "0");
			XmlUtil.AddXmlElement(xml, dbci, "ExtraConnectionString", ExtraConnectionString);
			XmlUtil.AddXmlElement(xml, dbci, "UseCustomConnectionString", UseCustomConnectionString ? "1" : "0");
			XmlUtil.AddXmlElement(xml, dbci, "CustomConnectionString", CustomConnectionString);

			parent.AppendChild(dbci);
		}
		#endregion

		#region LoadFromXml(XmlDocument xml, XmlNode parent)
		public void LoadFromXml(XmlDocument xml, XmlNode parent)
		{
			try
			{
				XmlNode dbci = parent["DbConnectionInfo"];

				if (dbci["StorageType"] != null && dbci["StorageType"].InnerText != null)
					_storageType = DbmlManager.Lib.Database.StorageType.ToEnum(dbci["StorageType"].InnerText);
				else
					_storageType = StorageTypeEnum.SqlServer;  // default

				_serverName = dbci["ServerName"].InnerText.Trim();
				_dbName = dbci["DbName"].InnerText.Trim();

				if (dbci["Port"] != null && dbci["Port"].InnerText != null)
					_port = dbci["Port"].InnerText.Trim();
				else
					_port = "3306";

				string encrypted = "0";
				string hashKey = string.Empty;

				try
				{
					XmlNode node = dbci["Encrypted"];
					if (node != null)
					{
						encrypted = node.InnerText;
						if (encrypted == "1")
							hashKey = dbci["Hash"].InnerText;
					}

					if (encrypted == "1")
					{
						string fullPassword = hashKey + CPUId + MACAddr;
            //_userName = EncryptUtil.DecryptString(dbci["UserName"].InnerText, fullPassword); 
            //_password = EncryptUtil.DecryptString(dbci["Password"].InnerText, fullPassword);
					}
					else
					{
						_userName = dbci["UserName"].InnerText.Trim();
						_password = dbci["Password"].InnerText.Trim();
					}
				}
				catch
				{
				}

				string authStringVal = dbci["AuthenticationMethod"].InnerText;
				int authIntVal = Int32.Parse(authStringVal);
				_authenticationMethod = (DbAuthenticationMethods) authIntVal;
				_appendExtraConnectionString = dbci["AppendExtraConnectionString"].InnerText == "1";
				_extraConnectionString = dbci["ExtraConnectionString"].InnerText.Trim();
				_useCustomConnectionString = dbci["UseCustomConnectionString"].InnerText == "1";
				_customConnectionString = dbci["CustomConnectionString"].InnerText.Trim();
			}
			catch
			{
			}
		}
		#endregion

		// Private Properties

		#region CPUId
		private string CPUId
		{
			get
			{
        //if (_cpu == "")
        //  _cpu = MachineInfo.CreateInstance().GetCPUId();
				return _cpu;
			}
		}
		private string _cpu = "";
		#endregion

		#region MACAddr
		private string MACAddr
		{
			get
			{
        //if (_macAddress == "")
        //  _macAddress = MachineInfo.CreateInstance().GetMACAddress();
				return _macAddress;
			}
		}
		private string _macAddress = "";
		#endregion

    // Private Methods

    #region SetAuthVal(ref DbAuthenticationMethods e, DbAuthenticationMethods newVal)
    private void SetAuthVal(ref DbAuthenticationMethods e, DbAuthenticationMethods newVal)
    {
      DbAuthenticationMethods oldVal = e;
      e = newVal;

      if (oldVal != newVal && !HasChanges)
      {
        // Only fire the ObjectChanged event the first time
        // a field within the object changes.
        _hasChanges = true;
        FireObjectChangedEvent();
      }
    }
    #endregion
  }
}
